/******************************************************************************/
//	FSM.h	-	Provides functionality to transition between states
/******************************************************************************/
	
#ifndef _FSM_H_
#define	_FSM_H_

#include "objectbase.h"

#include "State.h"
#include "Event.h"

#include "KlinkTimer.h"

#include <map>
#include <list>
#include <vector>
using namespace std;

class CActor;

class FSM  : public CObjectBase
{
	friend class FSMScript;
	protected:
		
		// Transition Table (Use: table[ a state id ][ an event id ] )
		map < int, map< Event::EventId, CState* > >  m_table;

		// All possible states for this machine
		vector<CState*> m_states;

		CState		*m_pStateCurrent,			//	initial/current state.
					*m_pStateNext;				//	next state.
		
		// Stores events waiting to be processed
		list<Event*> m_eventQueue;

		// Controls the rate at which transitions can occur
		CKlinkTimer	m_transitionTimer;

		/******************************************************************************/
		//	Transition	-	Computes next state for FSM
		/******************************************************************************/
		void Transition();

public:
		// constructor
		FSM();

		// destructor
		virtual ~FSM();
		
		/******************************************************************************/
		//	Init	-	Initializes Object
		/******************************************************************************/
		void	Init();

		/******************************************************************************/
		//	Initialize	-	Initializes FSM to link with Actor
		//	In:  pActor  the actor that this FSM is used for
		/******************************************************************************/
		void	Initialize(CActor *pActor);

		/******************************************************************************/
		//	Update	-	Updates FSM, switching states if needed, etc..
		/******************************************************************************/
		bool Update();

		/******************************************************************************/
		//	Shutdown	-	Shutdown the Object
		/******************************************************************************/
		void	Shutdown();

		/******************************************************************************/
		//	SetInitialStates	-	Sets the initial states for the FSM.
		//
		//	In:		pStateStart	-	The state the FSM should start in
		//	In:		pStateNext	-	The state the FSM should transition to on it's first update
		/******************************************************************************/
		void SetInitialStates(CState *	pStateStart, CState * pStateNext = NULL);

		/******************************************************************************/
		//	EnQueueEvent	-	queues events to be processed by the FSM in the transition 
		//						function. Only events with ID defined for the FSM should be used.
		//
		//	Return:		true if ok, false if ID invalid for FSM.
		/******************************************************************************/
		bool EnQueueEvent(Event* pEvent);

		/******************************************************************************/
		//	ClearTransitionTable - clears the FSM's transition table so that it is empty.
		//						 - does not handle the memory for the states it contains.
		//  
		/******************************************************************************/
		void ClearTransitionTable();


		/******************************************************************************/
		//	GetEventQueueSize - returns the size of the FSM's event queue.
		/******************************************************************************/
		int GetEventQueueSize();

		/******************************************************************************/
		//	PushBackState - pushes a state on the back of the fsm's state vector.
		//	In:  pStateIn  the state to push onto the fsm
		/******************************************************************************/
		void PushBackState(CState * pStateIn);
};

#endif // _FSM_H_